#include "common.h"
#include "net.h"
#include "zm_spec.h"

/*
 * port: local port
 * time: send and recv timeout value,unit seconds
 */
int create_bind_udp_socket(int port, int time)
{
	int socket_fd;

	socket_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(socket_fd == -1) 
	{
		//perror("unable to create socket:");
		dzlog_error("create socket fail:%s\n",strerror(errno));
		return -1;
	}

#if 0
	/* reuse socket addr */
	int reuse_opt = 1;
	if((setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&reuse_opt,sizeof(reuse_opt))) == -1)
	{
		dzlog_error("setsockopt reuse fail:%s\n",strerror(errno));
		close(socket_fd);
		return -1;
	}
	// multicast 
	unsigned char multi_loop = 1;
	if ((setsockopt(socket_fd,IPPROTO_IP,IP_MULTICAST_LOOP,&multi_loop,sizeof(unsigned char))) == -1) 
	{
		dzlog_error("setsockopt multicastloop fail:%s\n",strerror(errno));
		close(socket_fd);
		return -1;
	}

	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	if(setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))==-1)
	{
		dzlog_error("setsockopt addmembership fail:%s\n",strerror(errno));
		close(socket_fd);
		return -1;
	}
#endif
	// broadcast 
	const int on = 1;
	if(setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on))<0)
	{
		dzlog_error("setsockopt broadcast error:%s\n",strerror(errno));
		close(socket_fd);
		return -1;
	}
	struct timeval timeout;
	if(time > 0)
	{
		timeout.tv_sec = time;
		timeout.tv_usec = 0;
		setsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
		setsockopt(socket_fd,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
	}
	struct sockaddr_in local_addr;
	memset(&local_addr,0,sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	local_addr.sin_port = htons(port);

	if(bind(socket_fd,(struct sockaddr*)&local_addr,sizeof(local_addr))<0)
	{
		dzlog_error("bind error:%s\n",strerror(errno));
		close(socket_fd);
		return -1;
	}

	return socket_fd;
}

int broadcast_message(int sockfd, const char *buff, int len)
{
	struct sockaddr_in broad_addr;
	int ret = -1;

	broad_addr.sin_family = AF_INET;
	broad_addr.sin_addr.s_addr = htons(INADDR_BROADCAST);
	broad_addr.sin_port = htons(BROADCAST_PORT);

	do
	{
		ret = sendto(sockfd,buff,len,0, (struct sockaddr*)&broad_addr,sizeof(struct sockaddr_in));
		if(ret < 0)
		{
			dzlog_error("sendto broadcast addr error:%s\n",strerror(errno));
			return -1;
		}
	}while(ret < len && errno == EINTR);


	dzlog_debug("sendto broadcast addr success,ret = %d.\n",ret);

	return 0;
}
		

